package com.seo.proxy.ban;

import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;

public class BanManager {

	private final Logger LOGGER = Logger.getLogger(getClass());

	private static final int MIN_REQUEST_COUNT = 10;

	private static final float MIN_URL_RATIO = 0.2f;

	private static final long BAN_DURATION = 60 * 60 * 1000;

	private Map<String, BanInfo> banInfos = new HashMap<String, BanInfo>();

	public BanManager() {
	}

	public boolean isIpBanned(String ip) {
		BanInfo banInfo = banInfos.get(ip);
		return banInfo != null && banInfo.banned;
	}

	public void request(URL url, String ip, boolean withUrl) {
		if (url.getPath().contains("check")) {
			return;
		}
		
		BanInfo banInfo = banInfos.get(ip);
		if (banInfo == null) {
			banInfo = new BanInfo();
			banInfos.put(ip, banInfo);
		}
		banInfo.lastRequestTime = System.currentTimeMillis();
		banInfo.requestCount++;
		if (withUrl) {
			banInfo.requestWithUrlCount++;
		}

		if (banInfo.requestCount > MIN_REQUEST_COUNT && (float) banInfo.requestWithUrlCount / banInfo.requestCount < MIN_URL_RATIO) {
			LOGGER.info("Banned " + ip + ". Request count - " + banInfo.requestCount + ", with url - " + banInfo.requestWithUrlCount);
			banInfo.banned = true;
			banInfo.unbanTime = System.currentTimeMillis() + BAN_DURATION;
		}
	}

	public void unban() {
		long time = System.currentTimeMillis();
		Iterator<Entry<String, BanInfo>> it = banInfos.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, BanInfo> entry = it.next();
			if ((entry.getValue().banned && entry.getValue().unbanTime <= System.currentTimeMillis()) || (time - entry.getValue().lastRequestTime > BAN_DURATION)) {
				it.remove();
			}
		}
	}
}

class BanInfo {
	boolean banned = false;
	int requestCount;
	int requestWithUrlCount;
	long unbanTime;
	long lastRequestTime;
}
